﻿#include "StdAfx.h"

#include "Camera.h"

#include <d3dx9.h>

#include "Game.h"
#include "D3DX.h"

Camera::Camera(CGame* game)
:Object(game)
//:mGame(game)
,mCamDist(20.0f)
,mDegree(0.0f)
,mPitchYawRoll(0,0,0)
,mPitchYawRollLast(0,0,0)
,mPos(0,0,10)
,mPosLast(0,0,0)
,mMouseX(0)
,mMouseY(0)
,mDragStartX(0)
,mDragStartY(0)
,mMouseRotateClicked(false)
,mMouseMoveClicked(false)
{
	//나 지금 고갱목록에 신청했으니 신문좀 보내주세요
	mGame->AddMouseEventListener(this);
	mGame->AddKeyEventListener(this);
}

Camera::~Camera(void)
{
	//나 죽었으니 신문 그만 보내
	mGame->DelMouseEventListener(this);
	mGame->DelKeyEventListener(this);
}

bool Camera::Tick()
{
	return true;
}

bool Camera::PrepareRender()
{
	return true;
}

void Camera::SetMatrices()
{
	if ( !mGame )
		return;

	LPDIRECT3DDEVICE9 device = mGame->GetDx()->GetD3DDevice();
	if ( !device )
		return;

	D3DXMATRIXA16 matWorld;
	D3DXMatrixIdentity(&matWorld);
	D3DXMatrixTranslation(&matWorld, mPos.x, mPos.y, mPos.z);
	device->SetTransform( D3DTS_WORLD, &matWorld );

	D3DXMATRIXA16 matView;
	D3DXMatrixIdentity(&matView);
	D3DXMatrixRotationYawPitchRoll( &matView, mPitchYawRoll.y, mPitchYawRoll.x, mPitchYawRoll.z );
	matView._41 = -matView._31 * mCamDist;
	matView._42 = -matView._32 * mCamDist;
	matView._43 = -matView._33 * mCamDist;

	D3DXMatrixInverse( &matView, NULL, &matView );
	device->SetTransform( D3DTS_VIEW, &matView );

	D3DXMATRIXA16 matProj;
	D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, (float)(mGame->GetWindowWidth())/(float)(mGame->GetWindowHeight()), 1.0f, 10000.0f );
	device->SetTransform( D3DTS_PROJECTION, &matProj );
}

void Camera::MouseEventMove( MouseEvent& evt )
{
	mMouseX = evt._x;
	mMouseY = evt._y;
	
	if ( mMouseRotateClicked )
	{
		int deltaX = mMouseX - mDragStartX;
		int deltaY = mMouseY - mDragStartY;
		float mouseSensitivity = 0.01f;
		mPitchYawRoll.y = mPitchYawRollLast.y + (deltaX * mouseSensitivity);
		mPitchYawRoll.x = mPitchYawRollLast.x + (deltaY * mouseSensitivity);
	}

	if ( mMouseMoveClicked )
	{
		int deltaX = mMouseX - mDragStartX;
		int deltaY = mMouseY - mDragStartY;

		LPDIRECT3DDEVICE9 device = mGame->GetDx()->GetD3DDevice();
		D3DXMATRIXA16 matView;
		device->GetTransform( D3DTS_VIEW, &matView );
		D3DXMatrixInverse( &matView, NULL, &matView );

		D3DXVECTOR3 dir(0,0,1);
		D3DXVECTOR3 updir(0,1,0);
		D3DXVec3TransformNormal(&dir, &dir, &matView);
		D3DXVec3TransformNormal(&updir, &updir, &matView);
		D3DXVECTOR3 rightDir(1,0,0);
		D3DXVec3Cross(&rightDir,&updir,&dir);
		//CLog("%f, %f, %f", rightDir.x, rightDir.y, rightDir.z);

		dir.y = 0;
		D3DXVec3Normalize(&dir,&dir);
		rightDir.y = 0;
		D3DXVec3Normalize(&rightDir,&rightDir);

		float mouseSensitivity = 0.1f;
		mPos = mPosLast + (deltaX * mouseSensitivity * rightDir) + (deltaY * mouseSensitivity * (dir*-1.f));
		//CLog("%f, %f, %f", mPos.x, mPos.y, mPos.z);
	}
}

void Camera::MouseEventClick( MouseEvent& evt )
{
	mDragStartX = mMouseX;
	mDragStartY = mMouseY;

	if ( evt._button == BTN_R_UP )
	{
		if ( mMouseRotateClicked )
		{
			mMouseRotateClicked = false;
		}
	}
	else if ( evt._button == BTN_R_DOWN )
	{
		mPitchYawRollLast = mPitchYawRoll;
		mMouseRotateClicked = true;
	}
	else if ( evt._button == BTN_M_DOWN )
	{
		mPosLast = mPos;
		mMouseMoveClicked = true;
	}
	else if ( evt._button == BTN_M_UP )
	{
		if ( mMouseMoveClicked )
			mMouseMoveClicked = false;
	}
}

void Camera::MouseEventWheel(MouseEvent& evt)
{
	LPDIRECT3DDEVICE9 device = mGame->GetDx()->GetD3DDevice();
	D3DXMATRIXA16 matView;
	device->GetTransform( D3DTS_VIEW, &matView );
	D3DXMatrixInverse( &matView, NULL, &matView );

	D3DXVECTOR3 dir(0,0,1);
	D3DXVec3TransformNormal(&dir, &dir, &matView);

	// wheel up
	if ( evt._wheel < 0 )
	{
		mPos += dir;
	}
	else // wheel down
	{
		mPos -= dir;
	}
}

RayData Camera::GetPickRay()
{
	RayData ret;
	if ( !mGame )
		return ret;

	LPDIRECT3DDEVICE9 device = mGame->GetDx()->GetD3DDevice();
	if ( !device )
		return ret;

 	D3DXMATRIXA16 matProj, matView, m;
 	D3DXMatrixIdentity(&matView);
 	D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, (float)mGame->GetWindowWidth() / (float)mGame->GetWindowHeight(), 1.0f, 1000.0f );
 	device->SetTransform( D3DTS_PROJECTION, &matProj );
 	D3DXVECTOR3 v;
 
 	v.x =  ( ( ( 2.0f * mMouseX ) / mGame->GetWindowWidth() ) - 1 ) / matProj._11;
 	v.y = -( ( ( 2.0f * mMouseY ) / mGame->GetWindowHeight() ) - 1 ) / matProj._22;
 	v.z =  1.0f;
 
	D3DXVECTOR3 vOrig, vDir;
 	device->GetTransform( D3DTS_VIEW, &matView);	//초기 view값을 받아 matView에 세팅한다.
 	D3DXMatrixInverse(&m, NULL, &matView);
 	vDir.x = v.x*m._11 + v.y*m._21 + v.z*m._31;
 	vDir.y = v.x*m._12 + v.y*m._22 + v.z*m._32;
 	vDir.z = v.x*m._13 + v.y*m._23 + v.z*m._33;
 	vOrig.x = m._41;
 	vOrig.y = m._42;
 	vOrig.z = m._43;

	ret._ori = vOrig;
	ret._dir = vDir;

	return ret;
}

void Camera::KeyEventMsg( KeyEvent& evt )
{
	int a=0;
}
